package com.sdnc.common.beetlsql;

import org.beetl.sql.clazz.SQLType;
import org.beetl.sql.core.ExecuteContext;
import org.beetl.sql.core.InterceptorContext;
import org.beetl.sql.core.SqlId;
import org.beetl.sql.ext.DebugInterceptor;

import java.util.Collection;
import java.util.List;

/**
 * 配置输出请求的SQL信息
 */
public class CustomizeDebugInterceptor extends DebugInterceptor {

	@Override
	public void before(InterceptorContext ctx) {
		ExecuteContext executeContext = ctx.getExecuteContext();
		ctx.put("debug.time", System.currentTimeMillis());
		String jdbcSql = formatSql(ctx.getExecuteContext().sqlResult.jdbcSql).strip();
		List<String> jdbcParas = formatParas(ctx.getExecuteContext().sqlResult.jdbcPara);
		StringBuilder sb = new StringBuilder();
		String lineSeparator = System.getProperty("line.separator", "\n");
		sb.append("┏━━━━━ Debug [")
				.append(formatSqlId(executeContext))
				.append("] ━━━")
				.append(lineSeparator)
				.append("┣ 编译语句：\t ").append(jdbcSql)
				.append(lineSeparator)
				.append("┣ 编译参数：\t ").append(jdbcParas)
				.append(lineSeparator);
		StringBuilder sql = new StringBuilder(jdbcSql.length() + 100);
		char[] jdbcSqlChars = jdbcSql.toCharArray();
		int length = jdbcSqlChars.length, j = 0;
		for (int i = 0; i < length; ++i) {
			char c = jdbcSqlChars[i];
			if (c == '?') {
				sql.append("'").append(jdbcParas.get(j++)).append("'");
			} else {
				sql.append(c);
			}
		}
		sb.append("┣").append(lineSeparator);
		sb.append("┣ 运行语句：\t ").append(sql).append(lineSeparator);
		sb.append("┣").append(lineSeparator);
		RuntimeException ex = new RuntimeException();
		StackTraceElement[] traces = ex.getStackTrace();
		int index = lookBusinessCodeInTrace(traces);
		StackTraceElement bussinessCode = traces[index];
		String className = bussinessCode.getClassName();
		int line = bussinessCode.getLineNumber();
		sb.append("┣ 代码位置：\t ").append(className)
				.append(".").append("(")
				.append(bussinessCode.getFileName())
				.append(":").append(line).append(")")
				.append(lineSeparator);
		ctx.put("logs", sb);
	}

	@Override
	public void after(InterceptorContext ctx) {
		ExecuteContext executeContext = ctx.getExecuteContext();
		SqlId sqlId = executeContext.sqlId;
		if (this.isSimple(sqlId)) {
			this.simpleOut(ctx);
			return;
		}
		long time = System.currentTimeMillis();
		long start = (Long) ctx.get("debug.time");
		String lineSeparator = System.getProperty("line.separator", "\n");
		StringBuilder sb = (StringBuilder) ctx.get("logs");
		sb.append("┣ 执行时间：\t " + (time - start) + "ms").append(lineSeparator);
		SQLType sqlType = ctx.getExecuteContext().sqlSource.sqlType;
		Object result = ctx.getExecuteContext().executeResult;
		if (sqlType.isUpdate()) {
			sb.append("┣ 更新行数：\t [");

			if (result.getClass().isArray()) {
				int[] ret = (int[]) result;
				for (int i = 0; i < ret.length; i++) {
					if (i > 0) {
						sb.append(",");
					}
					sb.append(ret[i]);
				}
			} else {
				sb.append(result);
			}
			sb.append("]").append(lineSeparator);
		} else {
			if (result instanceof Collection) {
				sb.append("┣ 获取行数：\t [").append(((Collection) result).size()).append("]").append(lineSeparator);
			} else {
				sb.append("┣ 查询结果：\t [").append(result).append("]").append(lineSeparator);
			}
		}
		sb.append("┗━━━━━ Debug [").append(formatSqlId(executeContext)).append("] ━━━")
				.append(lineSeparator);
		println(sb.toString());
	}

	@Override
	protected int lookBusinessCodeInTrace(StackTraceElement[] traces) {
		for (int i = traces.length - 1; i >= 0; --i) {
			String name = traces[i].getClassName();
			if (name.indexOf("$Proxy") != -1 && traces[i].getLineNumber() == -1) {
				return i + 1;
			} else if (name.startsWith("org.beetl.sql.core.query")) {
				return i + 1;
			}
		}

		return 0;
	}

}
